#include "downloadcommand.h"
#include "NetworkCommonFunction.h"
#include "common.h"

#include <QFile>
#include <QThread>
#include <QDebug>
#include <boost/scoped_array.hpp>
extern "C"
{
#include <winsock2.h>
}

class TransferThread : public QThread
{
public:
	TransferThread(int transferId, const QString& filePath, const QString& saveFilePath);
protected:
	void run();
private:
	int m_TransferId;
	QString m_FilePath;
	QString m_SaveFilePath;
};

struct SocketCloser
{
	SocketCloser(int socket):
			m_Socket(socket)
	{
	}
	~SocketCloser()
	{
		closesocket(m_Socket);
	}

private:
	int m_Socket;
};

TransferThread::TransferThread(int transferId, const QString &filePath, const QString &saveFilePath):
		m_TransferId(transferId),
		m_FilePath(filePath),
		m_SaveFilePath(saveFilePath)
{

}

void TransferThread::run()
{
	int ret;
	int socket = ::socket(AF_INET, SOCK_STREAM, 0);
	if(socket == INVALID_SOCKET)
	{
		qDebug()<<"Create file browser transfer socket error";
		return;
	}

	SocketCloser socketCloser(socket);

	sockaddr_in serverAddr;
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_addr.s_addr = inet_addr( g_ServerIp.c_str() );
	serverAddr.sin_port = htons( g_FileBrowserTransferPort );

	ret = ::connect(socket, (SA*)&serverAddr, sizeof(serverAddr));
	if(ret == SOCKET_ERROR)
	{
		qDebug()<<"Connect to file browser transfer server error";
		return;
	}

	int clientId = GetClientId();
	if(!sendData(socket, FBtoNetworkCharP(clientId), sizeof(clientId)))
	{
		qDebug()<<"File browser send client id error";
		return;
	}

	int tmpTransferId = m_TransferId;
	if(!sendData(socket, FBtoNetworkCharP(tmpTransferId), sizeof(tmpTransferId)))
	{
		qDebug()<<"File browser send transfer id error";
		return;
	}

	QByteArray saveFilePathUtf8 = m_SaveFilePath.toUtf8();

	int saveFileNameLen = saveFilePathUtf8.size();
	if(!sendData(socket, FBtoNetworkCharP(saveFileNameLen), sizeof(saveFileNameLen)))
	{
		qDebug()<<"Send save file name length error";
		return;
	}

	if(!sendData(socket, saveFilePathUtf8.data(), saveFilePathUtf8.size()))
	{
		qDebug()<<"Send save file path error";
		return;
	}

	QFile file(m_FilePath);
	if(!file.exists())
	{
		qDebug()<<"File "<<m_FilePath<<" for transfer not exits";
		return;
	}

	if(! file.open(QFile::ReadOnly) )
	{
		qDebug()<<"Open "<<m_FilePath<<" for transfer error";
		return;
	}

	const int bufferSize = 500 * 1024;
	char* buffer = new char[bufferSize];
	boost::scoped_array<char> bufferContainer(buffer);

	long long fileSize = file.size();
	long long sendedSize = 0;
	while(true)
	{
		long long readSize = file.read(buffer, bufferSize);
		if(readSize == -1)
		{
			qDebug()<<"Read file "<<m_FilePath<<" for transfer error";
			break;
		}

		if(!sendData(socket, buffer, readSize))
		{
			qDebug()<<"Send file browser transfer data error";
			break;
		}

		sendedSize += readSize;
		if(sendedSize >= fileSize)
			break;
	}
}

DownloadCommand::DownloadCommand(int transferId, const QString &filePath, const QString &saveFilePath):
		m_TransferId(transferId),
		m_FilePath(filePath),
		m_SaveFilePath(saveFilePath)
{

}

bool DownloadCommand::doCommand(QString &responseData)
{
	TransferThread* transferThread = new TransferThread(m_TransferId, m_FilePath, m_SaveFilePath);
//	connect(transferThread, SIGNAL(terminated()),
//			transferThread, SLOT(deleteLater()));
	transferThread->start();
	return true;
}
